home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / amiexpress / source / ae / code / ax3.00 / startzmodem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1980-01-03  |  32.5 KB  |  1,640 lines

  1. #include "bbs.h"
  2.  
  3. #include "zmodem.h"
  4.  
  5. #define SLEEP_LOGOFF    2
  6.  
  7. short update_crc16(int cp, short crc);
  8. long update_crc32(int cp, long crc);
  9.  
  10. extern BPTR fh;
  11. extern char *SkipdFiles;
  12. extern long zbaud, zbufsize, TMPBT;
  13. extern int sendlen, doublebuffer, zresume, NumSkipd;
  14. extern char *sendbuff, *zdiskbuff, *zbuffer, sbuff[];
  15. extern ULONG STpos;
  16.  
  17. int tryzhdrtype;            /* Header type to send corresponding to Last rx close */
  18. int Zctlesc,start;        /* Don't escape control characters */
  19. int transfering=0;
  20. char txbuf[1024];
  21.  
  22. long chinseg;
  23. char ZPathname[257];
  24. long filesize;
  25. long resumesize;
  26. int Rxbuflen;
  27. int Rxflags;
  28.  
  29. int Rxframeind;                /* ZBIN ZBIN32, or ZHEX type of frame received */
  30. int Rxtype;                    /* Type of header received */
  31. int Rxcount;                    /* Count of data bytes received */
  32. char Rxhdr[4];                /* Received header */
  33. char Txhdr[4];                /* Transmitted header */
  34. long Rxpos;                    /* Received file position */
  35. long Txpos;                    /* Transmitted file position */
  36. int Txfcs32;                    /* TRUE means send binary frames with 32 bit FCS */
  37. int Crc32t;                    /* Display flag indicating 32 bit CRC being sent */
  38. int Crc32;                    /* Display flag indicating 32 bit CRC being received */
  39. char Attn[ZATTNLEN+1];        /* Attention string rx sends to tx on err */
  40. int lastsent;                /* Last char we sent */
  41. int zsrCDstat;
  42.  
  43. FILE *f;
  44.  
  45. //(RTS)
  46. /*
  47.  * ZMODEM protocol primitives
  48.  * Chuck Forsberg Omen Technology Inc.
  49.  *
  50.  * Entry point Functions:
  51.  *    zsbhdr(type, hdr) send binary header
  52.  *    zshhdr(type, hdr) send hex header
  53.  *    zgethdr(hdr, eflag) receive header - binary or hex
  54.  *    zsdata(buf, len, frameend) send data
  55.  *    zrdata(buf, len) receive data
  56.  *    stohdr(pos) store position data in Txhdr
  57.  *    long rclhdr(hdr) recover position offset from header
  58.  */
  59.  
  60. static long rclhdr(char *hdr);
  61. static void zputhex(int c), zmputs(char *s);
  62. static void zsda32(char *buf, int length, int frameend);
  63. static void zsdata(char *buf, int length, int frameend);
  64. static void zshhdr(int type, char *hdr);
  65. static void zsbh32(int type, char *hdr);
  66. static void zsbhdr(int type, char *hdr);
  67. static void stohdr(long pos), ackbibi(void), canit(void), putsec(void);
  68.  
  69. static int noxrd7(void), zdlread(void), zgethex(void), zrhhdr(char *hdr);
  70. static int zrbhdr(char *hdr), zrbhdr32(char *hdr), zgethdr(char *hdr);
  71. static int zrdat32(char *buf, int length), zrdata(char *buf, int length);
  72. static int procheader(char *name), zsendfile(char *buf, int blen);
  73. static int zsendfdata(void), getinsync(void), saybibi(void);
  74. static int rzfile(void), rzfiles(void), tryz(void);
  75. static int getzrxinit(void);
  76.  
  77. /*
  78.  * Read a character from the modem line with timeout.
  79.  *  Eat parity, XON and XOFF characters.
  80.  */
  81.  
  82.  
  83. static void ZErrDisplay(char *s)
  84. {
  85.  char temp[50];
  86.  
  87.  ZmodemStatPrint("12H");
  88.  ZmodemStatPrint("                             ");
  89.  ZmodemStatPrint("12H");
  90.  ZmodemStatPrint(s);
  91.  ZmodemStatPrint("12H");
  92.  strcpy(ZModemInfo.ZStat,s);
  93.  ZModemInfo.ErrorPos=ZModemInfo.RecPos;
  94.  sprintf(temp,"%ld    ",ZModemInfo.ErrorPos);
  95.  ZmodemStatPrint(temp);
  96. }
  97.  
  98.  
  99. static void ZPrintClear(char *s)
  100. {
  101.  ZmodemStatPrint(s);
  102.  ZmodemStatPrint("                             ");
  103. }
  104.  
  105.  
  106. static int noxrd7(void)
  107. {
  108.     register int c;
  109.  
  110.     for (;;) {
  111.         if ((c = readbyte()) < 0)            return c;
  112.         switch (c &= 0x7F)    {
  113.             case XON:
  114.             case XOFF:
  115.                 continue;
  116.             default:
  117.                 if (Zctlesc && !(c & 0x60))     continue;
  118.             case '\r':        case '\n':        case ZDLE:
  119.                 return c;
  120.         }
  121.     }
  122. }
  123.  
  124. /*
  125.  * Read a byte, checking for ZMODEM escape encoding
  126.  *  including CAN*5 which represents a quick abort
  127.  */
  128. static int zdlread(void)
  129. {
  130.     register int c;
  131.  
  132. again:
  133.     /* Quick check for non control characters */
  134.     if ((c = readbyte()) & 0x60)        return c;
  135.     switch (c)    {
  136.         case ZDLE:            break;
  137.         case 0x13:    case 0x93:    case 0x11:    case 0x91:
  138.             goto again;
  139.         default:
  140.             if (Zctlesc && !(c & 0x60))        goto again;
  141.             return c;
  142.     }
  143. again2:
  144.     zsrCDstat=CheckCarrier();
  145.     if(zsrCDstat==FALSE)        return CAN;
  146.     if ((c = readbyte()) < 0)    return c;
  147.  
  148.     if (c == CAN && (c = readbyte()) < 0)    return c;
  149.     if (c == CAN && (c = readbyte()) < 0)    return c;
  150.     if (c == CAN && (c = readbyte()) < 0)    return c;
  151.     switch (c) {
  152.         case CAN:            return GOTCAN;
  153.         case ZCRCE:        case ZCRCG:        case ZCRCQ:        case ZCRCW:
  154.             return (c | GOTOR);
  155.         case ZRUB0:            return 0x7F;
  156.         case ZRUB1:            return 0xFF;
  157.         case 0x13:    case 0x93:    case 0x11:    case 0x91:
  158.             goto again2;
  159.         default:
  160.             if (Zctlesc && ! (c & 0x60))    goto again2;
  161.             if ((c & 0x60) ==  0x40)        return(c ^ 0x40);
  162.             break;
  163.     }
  164.     sprintf(sbuff, "Bad escape sequence %x", c);
  165.     ZErrDisplay(sbuff);
  166.     return ERROR;
  167. }
  168.  
  169. /* Decode two lower case hex digits into an 8 bit byte value */
  170. static int zgethex(void)
  171. {
  172.     register int c, n;
  173.  
  174.     if ((c = noxrd7()) < 0)        return c;
  175.     n = c - '0';
  176.     if (n > 9)                    n -= ('a' - ':');
  177.     if (n & ~0xF)                return ERROR;
  178.     if ((c = noxrd7()) < 0)        return c;
  179.  
  180.     c -= '0';
  181.     if (c > 9)        c -= ('a' - ':');
  182.     if (c & ~0xF)    return ERROR;
  183.     c += (n<<4);
  184.     return c;
  185. }
  186.  
  187. /* Receive a hex style header (type and position) */
  188. static int zrhhdr(char *hdr)
  189. {
  190.     register int c;
  191.     register unsigned short crc;
  192.     register int n;
  193.  
  194.     if ((c = zgethex()) < 0)        return c;
  195.     Rxtype = c;
  196.     crc = update_crc16(c, 0);
  197.  
  198.     for (n=4; --n >= 0; ++hdr)    {
  199.         if ((c = zgethex()) < 0)
  200.             return c;
  201.         crc = update_crc16(c, crc);
  202.         *hdr = c;
  203.     }
  204.     if ((c = zgethex()) < 0)
  205.         return c;
  206.     crc = update_crc16(c, crc);
  207.     if ((c = zgethex()) < 0)
  208.         return c;
  209.     crc = update_crc16(c, crc);
  210.     if (crc & 0xFFFF) 
  211.     {
  212.         ZErrDisplay("Bad CRC"); return ERROR;
  213.     }
  214.     switch ( c = readbyte()) 
  215.     {
  216.         case 0x8D:
  217.         case 0xD:
  218.              /* Throw away possible cr/lf */
  219.             readbyte();
  220.     }
  221.     return Rxtype;
  222. }
  223.  
  224. /* Receive a binary style header (type and position) */
  225. static int zrbhdr(char *hdr)
  226. {
  227.     register int c, n;
  228.     register unsigned short crc;
  229.  
  230.     if ((c = zdlread()) & ~0xFF)
  231.         return c;
  232.     Rxtype = c;
  233.     crc = update_crc16(c, 0);
  234.  
  235.     for (n=4; --n >= 0; ++hdr) 
  236.     {
  237.         if ((c = zdlread()) & ~0xFF)
  238.             return c;
  239.         crc = update_crc16(c, crc);
  240.         *hdr = c;
  241.     }
  242.     if ((c = zdlread()) & ~0xFF)
  243.         return c;
  244.     crc = update_crc16(c, crc);
  245.     if ((c = zdlread()) & ~0xFF)
  246.         return c;
  247.     crc = update_crc16(c, crc);
  248.     if (crc & 0xFFFF)
  249.     {
  250.         ZErrDisplay("Bad CRC");
  251.         return ERROR;
  252.     }
  253.     return Rxtype;
  254. }
  255.  
  256. /* Receive a binary style header (type and position) with 32 bit FCS */
  257. static int zrbhdr32(char *hdr)
  258. {
  259.     register int c, n;
  260.     register unsigned long crc;
  261.  
  262.     if ((c = zdlread()) & ~0xFF)
  263.         return c;
  264.     Rxtype = c;
  265.     crc = 0xFFFFFFFFL; crc = update_crc32(c, crc);
  266.  
  267.     for (n=4; --n >= 0; ++hdr)
  268.     {
  269.         if ((c = zdlread()) & ~0xFF)
  270.             return c;
  271.         crc = update_crc32(c, crc);
  272.         *hdr = c;
  273.     }
  274.     for (n=4; --n >= 0;)
  275.     {
  276.         if ((c = zdlread()) & ~0xFF)
  277.             return c;
  278.         crc = update_crc32(c, crc);
  279.     }
  280.  
  281.     if (crc != 0xDEBB20E3L)
  282.     {
  283.         ZErrDisplay("Bad CRC");
  284.         return ERROR;
  285.     }
  286.     return Rxtype;
  287. }
  288.  
  289. /*
  290.  * Read a ZMODEM header to hdr, either binary or hex.
  291.  *  eflag controls local display of non zmodem characters:
  292.  *    0:  no display
  293.  *    1:  display printing characters only
  294.  *    2:  display all non ZMODEM characters
  295.  *   set Rxpos and return type of header.
  296.  *   Otherwise return negative on error.
  297.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  298.  */
  299. static int zgethdr(char *hdr)
  300. {
  301.     register int c, n, cancount;
  302.  
  303.     n = 1400 + zbaud;    /* Max bytes before start of frame */
  304.     Rxframeind = Rxtype = 0;
  305.  
  306. startover:
  307.     cancount = 5;
  308. again:
  309.     /* Return immediate ERROR if ZCRCW sequence seen */
  310.     switch (c = readbyte())
  311.     {
  312.         case RCDO:
  313.         case TIMEOUT: {
  314.             zsrCDstat=CheckCarrier();
  315.          if(zsrCDstat==FALSE)
  316.                     return NOCARRERROR;
  317.             goto fifi;
  318.             }
  319.         case CAN:
  320. gotcan:
  321.             if (--cancount <= 0) {
  322.                 c = ZCAN;
  323.                 goto fifi;
  324.             }
  325.             switch (c = readbyte())    {
  326.                 case TIMEOUT:
  327.                     goto again;
  328.                 case ZCRCW:
  329.                     c = ERROR;
  330.                 /* **** FALL THRU TO **** */
  331.                 case RCDO:
  332.                     goto fifi;
  333.                 default:
  334.                     break;
  335.                 case CAN:
  336.                     if (--cancount <= 0)
  337.                     {
  338.                         c = ZCAN; goto fifi;
  339.                     }
  340.                     goto again;
  341.             }
  342.     /* **** FALL THRU TO **** */
  343.         default:
  344. agn2:
  345.             if ( --n == 0)
  346.             {
  347.                 ZErrDisplay("Garbage count exceeded");
  348.                 return(ERROR);
  349.             }
  350.             goto startover;
  351.         case ZPAD|0x80:        /* This is what we want. */
  352.         case ZPAD:        /* This is what we want. */
  353.             break;
  354.     }
  355.     cancount = 5;
  356. splat:
  357.     switch (c = noxrd7())
  358.     {
  359.         case ZPAD:
  360.             goto splat;
  361.         case RCDO:
  362.         case TIMEOUT:
  363.             goto fifi;
  364.         default:
  365.             goto agn2;
  366.         case ZDLE:        /* This is what we want. */
  367.             break;
  368.     }
  369.  
  370.     switch (c = noxrd7())
  371.     {
  372.         case RCDO:
  373.         case TIMEOUT:
  374.             goto fifi;
  375.         case ZBIN:
  376.             Rxframeind = ZBIN;  Crc32 = FALSE;
  377.             c =  zrbhdr(hdr);
  378.             break;
  379.         case ZBIN32:
  380.             Crc32 = Rxframeind = ZBIN32;
  381.             c =  zrbhdr32(hdr);
  382.             break;
  383.         case ZHEX:
  384.             Rxframeind = ZHEX;  Crc32 = FALSE;
  385.             c =  zrhhdr(hdr);
  386.             break;
  387.         case CAN:
  388.             goto gotcan;
  389.         default:
  390.             goto agn2;
  391.     }
  392.     Rxpos = hdr[ZP3] & 0xFF;
  393.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0xFF);
  394.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0xFF);
  395.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0xFF);
  396. fifi:
  397.     switch (c)
  398.     {
  399.         case GOTCAN:
  400.             c = ZCAN;
  401.         /* **** FALL THRU TO **** */
  402.         case ZNAK:
  403.         case ZCAN:
  404.         case ERROR:
  405.         case TIMEOUT:
  406.         case RCDO:
  407.         /* **** FALL THRU TO **** */
  408.         default:
  409.             break;
  410.     }
  411.     return c;
  412. }
  413.  
  414. static int zrdat32(char *buf, int length)
  415. {
  416.     register int c, d;
  417.     register unsigned long crc;
  418.     register char *end;
  419.  
  420.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  421.     while (buf <= end)
  422.     {
  423.         if ((c = zdlread()) & ~0xFF)
  424.         {
  425. crcfoo:
  426.             switch (c)
  427.             {
  428.                 case GOTCRCE:
  429.                 case GOTCRCG:
  430.                 case GOTCRCQ:
  431.                 case GOTCRCW:
  432.                     crc = update_crc32(d=c, crc);
  433.                     if ((c = zdlread()) & ~0xFF)
  434.                         goto crcfoo;
  435.                     crc = update_crc32(c, crc);
  436.                     if ((c = zdlread()) & ~0xFF)
  437.                         goto crcfoo;
  438.                     crc = update_crc32(c, crc);
  439.                     if ((c = zdlread()) & ~0xFF)
  440.                         goto crcfoo;
  441.                     crc = update_crc32(c, crc);
  442.                     if ((c = zdlread()) & ~0xFF)
  443.                         goto crcfoo;
  444.                     crc = update_crc32(c, crc);
  445.                     if (crc != 0xDEBB20E3L)
  446.                     {
  447.                         ZErrDisplay("Bad CRC");
  448.                         return ERROR;
  449.                     }
  450.                     Rxcount = length - (end - buf);
  451.                     return d;
  452.                 case GOTCAN:
  453.                     ZErrDisplay("Sender Canceled");
  454.                     return ZCAN;
  455.                 case TIMEOUT:
  456.                     zsrCDstat=CheckCarrier();
  457.                     if(zsrCDstat==FALSE) {
  458.                         return ERROR;
  459.                     }
  460.                     ZErrDisplay("TIMEOUT");
  461.                     return c;
  462.                 default:
  463.                     ZErrDisplay("Bad data subpacket");
  464.                     return c;
  465.             }
  466.         }
  467.         *buf++ = c;
  468.         crc = update_crc32(c, crc);
  469.     }
  470.     ZErrDisplay("Data subpacket too long");
  471.     return ERROR;
  472. }
  473.  
  474. /*
  475.  * Receive array buf of max length with ending ZDLE sequence
  476.  *  and CRC.  Returns the ending character or error code.
  477.  *  NB: On errors may store length+1 bytes!
  478.  */
  479. static int zrdata(char *buf, int length)
  480. {
  481.     register int c, d;
  482.     register unsigned short crc;
  483.     register char *end;
  484.  
  485.     if (Rxframeind == ZBIN32)
  486.         return zrdat32(buf, length);
  487.  
  488.     crc = Rxcount = 0;  end = buf + length;
  489.     while (buf <= end)
  490.     {
  491.         if ((c = zdlread()) & ~0xFF)
  492.         {
  493. crcfoo:
  494.             switch (c)
  495.             {
  496.                 case GOTCRCE:
  497.                 case GOTCRCG:
  498.                 case GOTCRCQ:
  499.                 case GOTCRCW:
  500.                     crc = update_crc16(d=c, crc);
  501.                     if ((c = zdlread()) & ~0xFF)
  502.                         goto crcfoo;
  503.                     crc = update_crc16(c, crc);
  504.                     if ((c = zdlread()) & ~0xFF)
  505.                         goto crcfoo;
  506.                     crc = update_crc16(c, crc);
  507.                     if (crc & 0xFFFF)
  508.                     {
  509.                         ZErrDisplay("Bad CRC");
  510.                         return ERROR;
  511.                     }
  512.                     Rxcount = length - (end - buf);
  513.                     return d;
  514.                 case GOTCAN:
  515.                     ZErrDisplay("Sender Canceled");
  516.                     return ZCAN;
  517.                 case TIMEOUT:
  518.                     zsrCDstat=CheckCarrier();
  519.                     if(zsrCDstat==FALSE) {
  520.                         return ERROR;
  521.                     }
  522.                     ZErrDisplay("TIMEOUT");
  523.                     return c;
  524.                 default:
  525.                     ZErrDisplay("Bad data subpacket");
  526.                     return c;
  527.             }
  528.         }
  529.         *buf++ = c;
  530.         crc = update_crc16(c, crc);
  531.     }
  532.     ZErrDisplay("Data subpacket too long");
  533.     return ERROR;
  534. }
  535.  
  536.  
  537. /* Recover a long integer from a header */
  538. static long rclhdr(char *hdr)
  539. {
  540.     register long l;
  541.  
  542.     l = (hdr[ZP3] & 0xFF);
  543.     l = (l << 8) | (hdr[ZP2] & 0xFF);
  544.     l = (l << 8) | (hdr[ZP1] & 0xFF);
  545.     l = (l << 8) | (hdr[ZP0] & 0xFF);
  546.     return l;
  547. }
  548.  
  549. /*
  550.  * Send character c with ZMODEM escape sequence encoding.
  551.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  552.  */
  553. void zsendbyte(int c)
  554. {
  555.     /* Quick check for non control characters */
  556.     if (c & 0x60)
  557.         sendbyte(lastsent = c);
  558.     else 
  559.     {
  560.         switch (c &= 0xFF) 
  561.         {
  562.             case ZDLE:
  563.                 sendbyte(ZDLE);
  564.                 sendbyte(lastsent = (c ^= 0x40));
  565.                 break;
  566.             case 0xD:
  567.             case 0x8D:
  568.                 if (!Zctlesc && (lastsent & 0x7F) != '@')
  569.                     goto sendit;
  570.             /* **** FALL THRU TO **** */
  571.             case 0x10:
  572.             case 0x11:
  573.             case 0x13:
  574.             case 0x90:
  575.             case 0x91:
  576.             case 0x93:
  577.                 sendbyte(ZDLE);
  578.                 c ^= 0x40;
  579. sendit:
  580.                 sendbyte(lastsent = c);
  581.                 break;
  582.             default:
  583.                 if (Zctlesc && ! (c & 0x60)) 
  584.                 {
  585.                     sendbyte(ZDLE);
  586.                     c ^= 0x40;
  587.                 }
  588.                 sendbyte(lastsent = c);
  589.         }
  590.     }
  591. }
  592.  
  593. /* Send a byte as two hex digits */
  594. static void zputhex(int c)
  595. {
  596.     static char digits[] = "0123456789abcdef";
  597.  
  598.     sendbyte(digits[(c&0xF0)>>4]);
  599.     sendbyte(digits[(c)&0xF]);
  600. }
  601.  
  602. /*
  603.  * Send a string to the modem
  604.  */
  605. static void zmputs(char *s)
  606. {
  607.     while(*s)
  608.         sendbyte(*s++);
  609. }
  610.  
  611. static void zsda32(char *buf, int length, int frameend)
  612. {
  613.     register int c;
  614.     register unsigned long crc;
  615.  
  616.     crc = 0xFFFFFFFFL;
  617.     for (;--length >= 0; ++buf)
  618.     {
  619.         c = *buf & 0xFF;
  620.         if (c & 0x60)
  621.             sendbyte(lastsent = c);
  622.         else
  623.             zsendbyte(c);
  624.         crc = update_crc32(c, crc);
  625.     }
  626.     sendbyte(ZDLE); sendbyte(frameend);
  627.     crc = update_crc32(frameend, crc);
  628.  
  629.     crc = ~crc;
  630.     for (length=4; --length >= 0;)
  631.     {
  632.         zsendbyte((int)crc);
  633.         crc >>= 8;
  634.     }
  635. }
  636.  
  637. /*
  638.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  639.  */
  640. static void zsdata(char *buf, int length, int frameend)
  641. {
  642.     register unsigned short crc;
  643.  
  644.     if (Crc32t)
  645.         zsda32(buf, length, frameend);
  646.     else
  647.     {
  648.         crc = 0;
  649.         for (;--length >= 0; ++buf)
  650.         {
  651.             zsendbyte(*buf); crc = update_crc16(*buf, crc);
  652.         }
  653.         sendbyte(ZDLE); sendbyte(frameend);
  654.         crc = update_crc16(frameend, crc);
  655.  
  656.         crc = update_crc16(0, crc);
  657.         crc = update_crc16(0, crc);
  658.         zsendbyte(crc>>8); zsendbyte(crc);
  659.     }
  660.     if (frameend == ZCRCW)
  661.         sendbyte(XON);
  662. }
  663.  
  664. /* Send ZMODEM binary header hdr of type type */
  665. static void zsbh32(int type, char *hdr)
  666. {
  667.     register int n;
  668.     register unsigned long crc;
  669.  
  670.     sendbyte(ZBIN32);  zsendbyte(type);
  671.     crc = 0xFFFFFFFFL; crc = update_crc32(type, crc);
  672.  
  673.     for (n=4; --n >= 0; ++hdr)
  674.     {
  675.         crc = update_crc32(*hdr, crc);
  676.         zsendbyte(*hdr);
  677.     }
  678.     crc = ~crc;
  679.     for (n=4; --n >= 0;)
  680.     {
  681.         zsendbyte((int)crc);
  682.         crc >>= 8;
  683.     }
  684. }
  685.  
  686. /* Send ZMODEM HEX header hdr of type type */
  687. static void zshhdr(int type, char *hdr)
  688. {
  689.     register int n;
  690.     register unsigned short crc;
  691.  
  692.     sendbyte(ZPAD); sendbyte(ZPAD); sendbyte(ZDLE); sendbyte(ZHEX);
  693.     zputhex(type);
  694.     Crc32t = 0;
  695.  
  696.     crc = update_crc16(type, 0);
  697.     for (n=4; --n >= 0; ++hdr)
  698.     {
  699.         zputhex(*hdr); crc = update_crc16(*hdr, crc);
  700.     }
  701.     crc = update_crc16(0, crc);
  702.     crc = update_crc16(0, crc);
  703.     zputhex(crc>>8); zputhex(crc);
  704.  
  705.     /* Make it printable on remote machine */
  706.     sendbyte(0xD); sendbyte(0x8A);
  707.     /*
  708.      * Uncork the remote in case a fake XOFF has stopped data flow
  709.      */
  710.     if (type != ZFIN && type != ZACK)
  711.         sendbyte(XON);
  712. }
  713.  
  714. /* Send ZMODEM binary header hdr of type type */
  715. static void zsbhdr(int type, char *hdr)
  716. {
  717.     register int n;
  718.     register unsigned short crc;
  719.  
  720.     sendbyte(ZPAD); sendbyte(ZDLE);
  721.  
  722.     if (Crc32t=Txfcs32)
  723.         zsbh32(type, hdr);
  724.     else
  725.     {
  726.         sendbyte(ZBIN); zsendbyte(type); crc = update_crc16(type, 0);
  727.  
  728.         for (n=4; --n >= 0; ++hdr)
  729.         {
  730.             zsendbyte(*hdr);
  731.             crc = update_crc16(*hdr, crc);
  732.         }
  733.         crc = update_crc16(0, crc);
  734.         crc = update_crc16(0, crc);
  735.         zsendbyte(crc>>8);
  736.         zsendbyte(crc);
  737.     }
  738. }
  739.  
  740. /* Store long integer pos in Txhdr */
  741. static void stohdr(long pos)
  742. {
  743.     Txhdr[ZP0] = pos;
  744.     Txhdr[ZP1] = pos>>8;
  745.     Txhdr[ZP2] = pos>>16;
  746.     Txhdr[ZP3] = pos>>24;
  747. }
  748.  
  749. /*
  750.  * Ack a ZFIN packet, let byegones be byegones
  751.  */
  752. static void ackbibi(void)
  753. {
  754.     register int n;
  755.  
  756.     stohdr(0L);
  757.     for (n=3; --n>=0; )
  758.     {
  759.         purgeline();
  760.         zshhdr(ZFIN, Txhdr);
  761.         switch (readbyte())
  762.         {
  763.             case 'O':
  764.                 readbyte();    /* Discard 2nd 'O' */
  765.                 return;
  766.             case RCDO:
  767.                 return;
  768.             case TIMEOUT:
  769.             default:
  770.                 break;
  771.         }
  772.     }
  773. }
  774.  
  775. static void canit(void)
  776. {
  777.     static char canistr[] =
  778.     {
  779.      24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  780.     };
  781.  
  782.     zmputs(canistr);
  783. }
  784.  
  785.  
  786. /*
  787.  * Putsec writes the n characters of buf to receive file fh
  788.  * remember to put in write err checking in here... then longjmp..
  789.  */
  790. static void putsec(void)
  791. {
  792.     WriteAsync(zbuffer, chinseg);
  793.     if(zbuffer == zdiskbuff)
  794.         {
  795.         zbuffer += 10240L;
  796.         }
  797.     else
  798.         {
  799.         zbuffer = zdiskbuff;
  800.         }
  801.     chinseg = 0L;
  802. }
  803.  
  804. /*
  805.  * Receive a file with ZMODEM protocol
  806.  *  Assumes file name frame is in buffer
  807.  */
  808. static int rzfile(void)
  809. {
  810.     register int c, n;
  811.     long rxbytes;
  812.  
  813.     start=0;
  814.     if (procheader(zbuffer) == ERROR)
  815.         return(tryzhdrtype = ZSKIP);
  816.  
  817.     n = 10; rxbytes = resumesize;
  818.  
  819.     for (;;)
  820.     {
  821.         chinseg = 0L;
  822.         stohdr(rxbytes);
  823.         zshhdr(ZRPOS, Txhdr);
  824. nxthdr:
  825.         if(check_abort()) { putsec(); return ERROR; }
  826.  
  827.         switch (c = zgethdr(Rxhdr))
  828.         {
  829.             default:
  830.             case ZNAK:
  831.             case TIMEOUT:
  832.                 putsec();
  833.                 zsrCDstat=CheckCarrier();
  834.                 if(zsrCDstat==FALSE) {
  835.                     return ERROR;
  836.                 }
  837.                 if ( --n < 0)
  838.                 {
  839.                     return ERROR;
  840.                 }
  841.             case ZFILE:
  842.                 zrdata(zbuffer, 1024);
  843.                 continue;
  844.             case ZEOF:
  845.                 putsec();
  846.                 if (rclhdr(Rxhdr) != rxbytes)
  847.                     goto nxthdr;
  848.                     /*
  849.                      * Ignore eof if it's at wrong place - force
  850.                      *  a timeout because the eof might have gone
  851.                      *  out before we sent our zrpos.
  852.                      */
  853.  
  854.                 throughput(rxbytes-resumesize);
  855.                 ++Online_NFiles;
  856.                 if(!FreeDFlag)
  857.                     {
  858.                     ++DONF;
  859.                     }
  860.                 Aclose();
  861.                 return c;
  862.             case ERROR:    /* Too much garbage in header search error */
  863.                 putsec();
  864.                 if ( --n < 0)
  865.                 {
  866.                     return ERROR;
  867.                 }
  868.                 zmputs(Attn);
  869.                 continue;
  870.             case ZSKIP:
  871.                 putsec();
  872.                 Aclose();
  873.                 return c;
  874.             case ZDATA:
  875.                 if(!start)
  876.                     {
  877.                     throughput(0L);
  878.                     start=1;
  879.                     }
  880.                 if (rclhdr(Rxhdr) != rxbytes)
  881.                 {
  882.                     if ( --n < 0)
  883.                         return ERROR;
  884.                     putsec();
  885.                     zmputs(Attn);
  886.                     continue;
  887.                 }
  888. moredata:
  889.                 if(check_abort()) { putsec(); return ERROR; }
  890.  
  891.                 if(chinseg >= ((doublebuffer) ? 8192L : 16384L))
  892.                     {
  893.                     putsec();
  894.                     }
  895.  
  896.                 switch (c = zrdata(zbuffer+chinseg, 1024))
  897.                 {
  898.                     case ZCAN:
  899.                         putsec();
  900.                         return ERROR;
  901.                     case ERROR:    /* CRC error */
  902.                         putsec();
  903.                         if ( --n < 0)
  904.                         {
  905.                             ZErrDisplay("Too many errors");
  906.                             return ERROR;
  907.                         }
  908.                         zmputs(Attn);
  909.                         continue;
  910.                     case TIMEOUT:
  911.                         putsec();
  912.                         zsrCDstat=CheckCarrier();
  913.                         if(zsrCDstat==FALSE)
  914.                             {
  915.                             return ERROR;
  916.                             }
  917.                         if ( --n < 0)
  918.                         {
  919.                             ZErrDisplay("Too many errors");
  920.                             return ERROR;
  921.                         }
  922.                         continue;
  923.                     case GOTCRCW:
  924.                         n = 10;
  925.                         chinseg += Rxcount;
  926.                         rxbytes += Rxcount;
  927.                         stohdr(rxbytes);
  928.                         zshhdr(ZACK, Txhdr);
  929.                         sendbyte(XON);
  930.                         sprintf(sbuff, "2H%ld  ",rxbytes);
  931.                         ZmodemStatPrint(sbuff);
  932.                         sprintf(sbuff, "2H%ld%%  ",(ZModemInfo.Filesize?((100*rxbytes)/ZModemInfo.Filesize):0));
  933.                         ZmodemStatPrint(sbuff);
  934.                         itp(rxbytes-resumesize,1);
  935.                         ZModemInfo.RecPos=rxbytes;
  936.                         goto nxthdr;
  937.                     case GOTCRCQ:
  938.                         n = 10;
  939.                         chinseg += Rxcount;
  940.                         rxbytes += Rxcount;
  941.                         stohdr(rxbytes);
  942.                         zshhdr(ZACK, Txhdr);
  943.                         sprintf(sbuff, "2H%ld  ",rxbytes);
  944.                         ZmodemStatPrint(sbuff);
  945.                         sprintf(sbuff, "2H%ld%%  ",(ZModemInfo.Filesize?((100*rxbytes)/ZModemInfo.Filesize):0));
  946.                         ZmodemStatPrint(sbuff);
  947.                         itp(rxbytes-resumesize,1);
  948.                         ZModemInfo.RecPos=rxbytes;
  949.                         goto moredata;
  950.                     case GOTCRCG:
  951.                         n = 10;
  952.                         chinseg += Rxcount;
  953.                         rxbytes += Rxcount;
  954.                         sprintf(sbuff, "2H%ld  ",rxbytes);
  955.                         ZmodemStatPrint(sbuff);
  956.                         sprintf(sbuff, "2H%ld%%  ",(ZModemInfo.Filesize?((100*rxbytes)/ZModemInfo.Filesize):0));
  957.                         ZmodemStatPrint(sbuff);
  958.                         itp(rxbytes-resumesize,1);
  959.                         ZModemInfo.RecPos=rxbytes;
  960.                         goto moredata;
  961.                     case GOTCRCE:
  962.                         n = 10;
  963.                         chinseg += Rxcount;
  964.                         rxbytes += Rxcount;
  965.                         sprintf(sbuff, "2H%ld  ",rxbytes);
  966.                         ZmodemStatPrint(sbuff);
  967.                         sprintf(sbuff, "2H%ld%%  ",(ZModemInfo.Filesize?((100*rxbytes)/ZModemInfo.Filesize):0));
  968.                         ZmodemStatPrint(sbuff);
  969.                         itp(rxbytes-resumesize,1);
  970.                         ZModemInfo.RecPos=rxbytes;
  971.                         goto nxthdr;
  972.                 }
  973.         }
  974.     }
  975. }
  976.  
  977. static int zmodemreceive(char *flname)     /* NEED pathname!!! */
  978. {
  979.     register c;
  980.  
  981.     RecFileNames[0]='\0';
  982.     *(SkipdFiles+(NumSkipd*32))='\0';
  983.     strcpy(ZPathname, flname);
  984.  
  985.     tryzhdrtype = ZRINIT;
  986.     Zctlesc = FALSE;
  987.  
  988.     if (c=tryz())    {
  989.         if (c == ZCOMPL)            return TRUE;
  990.         if (c == ERROR)             goto fubar;
  991.         if (c == NOCARRERROR)        return FALSE;
  992.         if (c == ZFILE)    {
  993.             if (c = rzfiles())
  994.                 goto fubar;
  995.             return TRUE;
  996.         }
  997.     }
  998.     return FALSE;
  999.  
  1000. fubar:
  1001.     canit();
  1002.     Aclose();
  1003.     return FALSE;
  1004. }
  1005.  
  1006. /*
  1007.  * Initialize for Zmodem receive attempt, try to activate Zmodem sender
  1008.  *  Handles ZSINIT  frame
  1009.  *  Return ZFILE if Zmodem filename received, -1 on error,
  1010.  *   ZCOMPL if transaction finished,  else 0
  1011.  */
  1012. static int tryz(void)
  1013. {
  1014.     register int c, n;
  1015.  
  1016.     for (n=10; --n>=0; )
  1017.     {
  1018.         if(check_abort()) return ERROR;
  1019.         zsrCDstat=CheckCarrier();
  1020.         if(zsrCDstat==FALSE)
  1021.             {
  1022.             return NOCARRERROR;
  1023.             }
  1024.  
  1025.         /* Set buffer length (0) and capability flags */
  1026.         stohdr(0L);
  1027.         Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
  1028.         zshhdr(tryzhdrtype, Txhdr);
  1029.         if (tryzhdrtype == ZSKIP)    /* Don't skip too far */
  1030.             tryzhdrtype = ZRINIT;
  1031. again:
  1032.         switch (zgethdr(Rxhdr))
  1033.         {
  1034.             case NOCARRERROR:
  1035.                 return NOCARRERROR;
  1036.             case ZRQINIT:
  1037.                 continue;
  1038.             case ZEOF:
  1039.                 continue;
  1040.             case TIMEOUT:
  1041.                 continue;
  1042.             case ZFILE:
  1043.                 tryzhdrtype = ZRINIT;
  1044.                 c = zrdata(zbuffer, 1024);
  1045.                 if (c == GOTCRCW)
  1046.                     return ZFILE;
  1047.                 zshhdr(ZNAK, Txhdr);
  1048.                 goto again;
  1049.             case ZSINIT:
  1050.                 Zctlesc = TESCCTL & Rxhdr[ZF0];
  1051.                 if (zrdata(Attn, ZATTNLEN) == GOTCRCW)
  1052.                 {
  1053.                     stohdr(1L);
  1054.                     zshhdr(ZACK, Txhdr);
  1055.                     goto again;
  1056.                 }
  1057.                 zshhdr(ZNAK, Txhdr);
  1058.                 goto again;
  1059.             case ZFREECNT:
  1060.                 stohdr(1000000L);
  1061.                 zshhdr(ZACK, Txhdr);
  1062.                 goto again;
  1063.             case ZCOMMAND:
  1064.                 return ERROR;
  1065.             case ZCOMPL:
  1066.                 goto again;
  1067.             default:
  1068.                 continue;
  1069.             case ZFIN:
  1070.                 ackbibi();
  1071.                 return ZCOMPL;
  1072.             case ZCAN:
  1073.                 return ERROR;
  1074.         }
  1075.     }
  1076.     return 0;
  1077. }
  1078.  
  1079. /*
  1080.  * Receive 1 or more files with ZMODEM protocol
  1081.  */
  1082. static int rzfiles(void)
  1083. {
  1084.     register int c;
  1085.  
  1086.     for (;;) {
  1087.  
  1088.         if(check_abort()) return ERROR;
  1089.         zsrCDstat=CheckCarrier();
  1090.         if(zsrCDstat==FALSE)            return ERROR;
  1091.  
  1092.         switch (c = rzfile()) {
  1093.             case ZEOF:
  1094.             case ZSKIP:
  1095.                 switch (tryz())     {
  1096.                     case ZCOMPL:        return OK;
  1097.                     default:           return ERROR;
  1098.                     case ZFILE:          break;
  1099.                 }
  1100.                 continue;
  1101.             default:
  1102.                 return c;
  1103.             case ERROR:
  1104.                 return c;
  1105.         }
  1106.     }
  1107. }
  1108.  
  1109. static int CheckInPlayPens(char *s)
  1110. {
  1111.  BPTR lock1,lock2;
  1112.  UWORD loop;
  1113.  
  1114.  loop=0;
  1115.  
  1116.  do {
  1117.         if(loop==Cmds->AcLvl[LVL_NODE_NUMBER]) {
  1118.             loop++;
  1119.         }
  1120.         sprintf(GSTR1,"%snode%ld",Cmds->BBSLoc,loop);
  1121.         if(lock1=Lock(GSTR1,ACCESS_READ)) {
  1122.             sprintf(GSTR1,"%sNode%ld/PLAYPEN/%s",Cmds->BBSLoc,loop,s);
  1123.             if(lock2=Lock(GSTR1,ACCESS_READ)) {
  1124.                 UnLock(lock2);
  1125.                 UnLock(lock1);
  1126.                 return(1);
  1127.             }
  1128.                else if(IoErr()!=205) { UnLock(lock1); return(1); }
  1129.             UnLock(lock1);
  1130.         }
  1131.         loop++;
  1132.     } while(lock1!=NULL);
  1133.  return(0);
  1134. }
  1135.  
  1136. /*
  1137.  * Process incoming file information header
  1138.  */
  1139. static int procheader(char *name)
  1140. {
  1141.     register char *p;
  1142.     int stats;
  1143.     unsigned long seconds;
  1144.     char fullname[257],string[200];
  1145.     BPTR l;
  1146.  
  1147.     strcpy(ZModemInfo.FileName,name);
  1148.     sprintf(sbuff, "2H%s",name);
  1149.     ZPrintClear("2H");
  1150.     ZmodemStatPrint(sbuff);
  1151.     ZErrDisplay("Processing Incoming Header");
  1152.  
  1153.     stats=Check_For_File(name);
  1154.     if(stats==0)        stats=CheckInPlayPens(name);
  1155.     if(stats!=0)    {
  1156.         ZErrDisplay("File Exists!");
  1157. //1NOV92
  1158.         strcpy(SkipdFiles+(NumSkipd*32),name);
  1159.         NumSkipd+=1;
  1160.           *(SkipdFiles+(NumSkipd*32))='\0';
  1161.         return ERROR;
  1162.     }
  1163.      SendMasterUpload(name);
  1164.  
  1165.     strcpy(fullname, ZPathname);
  1166.     strcat(fullname, name);
  1167.     if((strlen(RecFileNames)+strlen(name)+1)<1024) {
  1168.         strcat(RecFileNames,name);
  1169.         strcat(RecFileNames," ");
  1170.     }
  1171.     else        return(ERROR);
  1172.  
  1173.     filesize = 0L;
  1174.     p = name + 1 + strlen(name);
  1175.     if (*p) sscanf(p, "%ld", &filesize);
  1176.  
  1177.     l = Lock(fullname, ACCESS_READ);
  1178.     if (l) UnLock(l);
  1179.  else zresume = FALSE;
  1180.  
  1181.     if(!Aopen(fullname, (long)((zresume) ? MODE_OLDFILE : MODE_NEWFILE))) {
  1182.         ZErrDisplay("File OPEN Error!");
  1183.         return ERROR;
  1184.     }
  1185.     Seek(fh, 0L, OFFSET_END);
  1186.     resumesize = Seek(fh, 0L, OFFSET_CURRENT);
  1187.     TMPBT=filesize;
  1188.  
  1189.     if(zresume)
  1190.         sprintf(string,"\tResuming %-12s %ld bytes [%6d]\n",name,filesize,resumesize);
  1191.     else {
  1192.         sprintf(string,"\tUploading %-12s %ld bytes\n",name,filesize);
  1193.           }
  1194.     CallersLog(string);
  1195.     UDLog(string);
  1196.  
  1197.     sprintf(sbuff, "2H%ld     ",filesize);
  1198.     ZModemInfo.Filesize=filesize;
  1199.     ZmodemStatPrint(sbuff);
  1200.  
  1201.     seconds = (((filesize-resumesize)/(long)(zbaud/10L))*100L)/95L;
  1202.     if(resumesize) {
  1203.         sprintf(sbuff, "2H%ld     ", resumesize);
  1204.         ZmodemStatPrint(sbuff);
  1205.         ZModemInfo.ResumePos=resumesize;
  1206.     }
  1207.     else    ZModemInfo.ResumePos=0L;
  1208.  
  1209.     sprintf(sbuff, "2H%ld mins %ld secs  (%d) ",seconds/60L, seconds % 60L,zbaud);
  1210.     ZmodemStatPrint(sbuff);
  1211.     ZModemInfo.ApxTime=seconds;
  1212.  
  1213.     ZErrDisplay("ZDATA");
  1214.     return OK;
  1215. }
  1216.  
  1217. /* flname = full file name(s) */
  1218.  
  1219. static int zmodemsend(char *flname)
  1220. {
  1221.     int rc,y;
  1222.     char *r, *fn;
  1223.     char string[200];
  1224.     unsigned long seconds;
  1225.     struct FileInfoBlock *FBlock;
  1226.     BPTR FLock;
  1227.  
  1228.     if(getzrxinit()==ERROR) return FALSE;
  1229.  
  1230.  sendmorefiles:
  1231.     fn = &ZPathname[0];
  1232.     strcpy(ZPathname, flname);
  1233.  
  1234.     if((FLock=Lock(fn,ACCESS_READ))==NULL)    return FALSE;
  1235.  
  1236.     if((FBlock=(struct FileInfoBlock *)AllocDosObject(DOS_FIB,NULL))==NULL) {
  1237.         UnLock(FLock);
  1238.         return FALSE;
  1239.     }
  1240.     if(Examine(FLock,FBlock)) {
  1241.         strcpy(ZModemInfo.FileName,FBlock->fib_FileName);
  1242.         if(FBlock->fib_Comment[0]=='F')    {
  1243.          FreeDFlag=1;
  1244.         }
  1245.         else{
  1246.             FreeDFlag=0;
  1247.         }
  1248.     } else {
  1249.         UnLock(FLock);
  1250.         FreeDosObject(DOS_FIB,FBlock);
  1251.         return FALSE;
  1252.     }
  1253.     UnLock(FLock);
  1254.     FreeDosObject(DOS_FIB,FBlock);
  1255.  
  1256.     strcpy(string,Conference_Location);
  1257.      if(IsFromIcon(string,"FREEDOWNLOADS"))
  1258.      {
  1259.         FreeDFlag=1;
  1260.     }
  1261.     if(!(fh = Open(fn, MODE_OLDFILE))) return FALSE;
  1262.  
  1263.     r = fn + strlen(fn);
  1264.     while (r>=ZPathname && *r!='/' && *r!=':') r--;
  1265.  
  1266.     strlwr(++r);
  1267.     strcpy(txbuf,r);
  1268.  
  1269.     /* VERY TEMP */
  1270.     Seek(fh, 0L, OFFSET_END);
  1271.     filesize = Seek(fh, 0L, OFFSET_BEGINNING);
  1272.  
  1273.     sprintf(string, "%ld %lo %o", filesize, 0L, 0L);
  1274.     strcpy(txbuf+strlen(txbuf)+1,string);
  1275.  
  1276.     y=strlen(string);
  1277.  
  1278.     TMPBT=filesize;
  1279.     if(FreeDFlag)
  1280.         strcpy(sbuff,"Free ");
  1281.     else
  1282.         sbuff[0]='\0';
  1283.  
  1284.     sprintf(string,"\t%sDownloading %-12s %ld bytes\n",sbuff,flname,filesize);
  1285.     (void)CallersLog(string);
  1286.     (void)UDLog(string);
  1287. (void)SendMasterDownload(ZModemInfo.FileName);
  1288.     ZPrintClear("2H");
  1289.     sprintf(sbuff, "2H%s",ZModemInfo.FileName);
  1290.     ZmodemStatPrint(sbuff);
  1291.  
  1292.     sprintf(sbuff, "2H%ld     ", filesize);
  1293.     ZmodemStatPrint(sbuff);
  1294.     ZModemInfo.Filesize=filesize;
  1295.  
  1296.     seconds = (filesize/(zbaud/10L));
  1297.     sprintf(sbuff, "2H%ld mins %ld secs  (%d) ",
  1298.                 seconds/60L, seconds % 60L,zbaud);
  1299.         ZModemInfo.ApxTime=seconds;
  1300.     ZmodemStatPrint(sbuff);
  1301.  
  1302.     rc = zsendfile(txbuf, (int)(2+y+strlen(txbuf)));
  1303.     Close(fh);
  1304.  
  1305.     switch(rc)    {
  1306.         case ERROR:            canit();        return FALSE;
  1307.         case OK:        case ZSKIP:
  1308.         default:
  1309.             ++Online_NFiles;
  1310.             if(!FreeDFlag)
  1311.                 ++DONF;
  1312.  
  1313.             flname = flname + strlen(flname)+1;
  1314.             if(*flname) goto sendmorefiles;
  1315.             saybibi();
  1316.             return TRUE;
  1317.     }
  1318. return(0);
  1319. }
  1320.  
  1321. /*
  1322.  * Get the receiver's init parameters
  1323.  */
  1324. static int getzrxinit(void)
  1325. {
  1326.     int n;
  1327.  
  1328.     zmputs("rz\r");
  1329.     stohdr(0L);
  1330.     zshhdr(ZRQINIT, Txhdr);
  1331.  
  1332.     for (n=10; --n>=0; ) {
  1333.         if(check_abort()) return ERROR;
  1334.  
  1335.         switch (zgethdr(Rxhdr)) {
  1336.             case ZCHALLENGE:    /* Echo receiver's challenge numbr */
  1337.                 stohdr(Rxpos);
  1338.                 zshhdr(ZACK, Txhdr);
  1339.                 continue;
  1340.             case ZCOMMAND:        /* They didn't see out ZRQINIT */
  1341.                 stohdr(0L);
  1342.                 zshhdr(ZRQINIT, Txhdr);
  1343.                 continue;
  1344.             case ZRINIT:
  1345.                 Rxflags = 0xFF & Rxhdr[ZF0];
  1346.                 Txfcs32 = (Rxflags & CANFC32);
  1347.                 Zctlesc |= Rxflags & TESCCTL;
  1348.                 Rxbuflen = (0xFF & Rxhdr[ZP0])+((0xFF & Rxhdr[ZP1])<<8);
  1349.  
  1350.                 return OK;
  1351.             case ZCAN:                return ERROR;
  1352.             case TIMEOUT:
  1353.                 zsrCDstat=CheckCarrier();
  1354.                 if(zsrCDstat==FALSE)
  1355.                     return ERROR;
  1356.  
  1357.                 stohdr(0L);
  1358.                 zshhdr(ZRQINIT, Txhdr);
  1359.                 continue;
  1360.             case ZRQINIT:
  1361.                 if (Rxhdr[ZF0] == ZCOMMAND)
  1362.                     continue;
  1363.             default:
  1364.                 zshhdr(ZNAK, Txhdr);
  1365.                 continue;
  1366.         }
  1367.     }
  1368.     return ERROR;
  1369. }
  1370.  
  1371. /* Send file name and related info */
  1372. static int zsendfile(char *buf, int blen)
  1373. {
  1374.     register int c, n;
  1375.  
  1376.     for (n=5; --n>=0;)    {
  1377.         if(check_abort()) return ERROR;
  1378.  
  1379.         Txhdr[ZF0] = 0;     /* file conversion request */
  1380.         Txhdr[ZF1] = 0;     /* file management request */
  1381.         Txhdr[ZF2] = 0;     /* file transport request */
  1382.         Txhdr[ZF3] = 0;
  1383.         zsbhdr(ZFILE, Txhdr);
  1384.         zsdata(buf, blen, ZCRCW);
  1385. again:
  1386.         c = zgethdr(Rxhdr);
  1387.         switch (c)    {
  1388.             case ZRINIT:
  1389.                 while ((c = readbyte()) > 0)
  1390.                     if (c == ZPAD)
  1391.                         goto again;
  1392.             case ZCAN:        case ZABORT:    case ZFIN:
  1393.                 return ERROR;
  1394.             case ZSKIP:        return c;
  1395.             case ZRPOS:
  1396.                 Seek(fh, Rxpos, OFFSET_BEGINNING);
  1397.                 STpos=Rxpos;
  1398.                 Txpos = Rxpos;
  1399.                 purgeline();
  1400.                 return zsendfdata();
  1401.             case TIMEOUT:
  1402.  
  1403.                 zsrCDstat=CheckCarrier();
  1404.                 if(zsrCDstat==FALSE) return ERROR;
  1405.                     return ERROR; 
  1406.             default:
  1407.                 continue;
  1408.         }
  1409.     }
  1410.     return ERROR;
  1411. }
  1412.  
  1413. /* Send the data in the file */
  1414. static int zsendfdata(void)
  1415. {
  1416.     register int c, e, n;
  1417.     int newcnt, goodblks = 0, goodneeded = 1;
  1418.     int blklen, maxblklen;
  1419.  
  1420.     blklen = maxblklen = 1024;
  1421.     if(Rxbuflen && Rxbuflen < maxblklen)
  1422.         blklen = maxblklen = Rxbuflen;
  1423.     throughput(0L);
  1424.  
  1425. somemore:
  1426.     if(checkline())
  1427.     {
  1428. waitack:
  1429.         switch (c = getinsync())
  1430.         {
  1431.             default:
  1432.             case ZCAN:
  1433.                 return ERROR;
  1434.             case ZSKIP:
  1435.                 return c;
  1436.             case ZACK:
  1437.                 break;
  1438.             case ZRPOS:
  1439.                 blklen = (blklen>>1 > 64) ? blklen>>1 : 64;
  1440.                 goodblks = 0;
  1441.                 goodneeded = (goodneeded<<1 < 64) ? goodneeded<<1 : 64;
  1442.                 break;
  1443.             case ZRINIT:
  1444.                 return OK;
  1445.         }
  1446.  
  1447.         while (checkline())
  1448.         {
  1449.             switch (readbyte())
  1450.             {
  1451.                 case CAN:
  1452.                 case ZPAD:
  1453.                     ZErrDisplay("ERROR Received");
  1454.                     goto waitack;
  1455.             }
  1456.         }
  1457.     }
  1458.  
  1459.     newcnt = Rxbuflen;
  1460.     stohdr(Txpos);
  1461.     zsbhdr(ZDATA, Txhdr);
  1462.  
  1463.     do
  1464.     {
  1465.         if(check_abort()) { waitwrite(); return ERROR; }
  1466.  
  1467.         n = Read(fh, txbuf, (long)blklen);
  1468.         if (n < blklen)
  1469.             e = ZCRCE;
  1470.         else if (Rxbuflen && (newcnt -= n) <= 0)
  1471.             e = ZCRCW;
  1472.         else
  1473.             e = ZCRCG;
  1474.  
  1475.         sendbuff = zbuffer;    /* tell sendbyte() to buffer the bytes in buffer */
  1476.         sendlen = 0;        /* sendlen is byte buffer count */
  1477.         zsdata(txbuf, n, e);
  1478.         sendbuff = 0L;
  1479.  
  1480.         while(checkline())
  1481.         {
  1482.             switch (readbyte())
  1483.             {
  1484.                 case CAN:
  1485.                 case ZPAD:
  1486.                     purgewrite();
  1487.                     ZErrDisplay("ERROR Received");
  1488.                     goto waitack;
  1489.             }
  1490.         }
  1491.  
  1492.         waitwrite();
  1493.         zsrCDstat=CheckCarrier();
  1494.         if(zsrCDstat==FALSE)
  1495.             {
  1496.             return ERROR;
  1497.             }
  1498.         sendbuffer(zbuffer, sendlen);
  1499.         if(zbuffer == zdiskbuff)
  1500.             zbuffer += 10240L;
  1501.         else
  1502.             zbuffer = zdiskbuff;
  1503.  
  1504.         Txpos += n;
  1505.  
  1506.         sprintf(sbuff, "2H%ld     ", Txpos);
  1507.         ZmodemStatPrint(sbuff);
  1508.         sprintf(sbuff, "2H%ld%%  ", (ZModemInfo.Filesize?((100*Txpos)/ZModemInfo.Filesize):0));
  1509.         ZmodemStatPrint(sbuff);
  1510.         itp(Txpos-STpos,0);
  1511.         ZModemInfo.RecPos=Txpos;
  1512.  
  1513.         if(blklen < maxblklen && ++goodblks > goodneeded)
  1514.         {
  1515.             blklen = (blklen<<1 < maxblklen) ? blklen<<1 : maxblklen;
  1516.             goodblks = 0;
  1517.             goodneeded = (goodneeded>>1 > 1) ? goodneeded>>1 : 1;
  1518.         }
  1519.  
  1520.         if (e == ZCRCW)
  1521.         {
  1522.             waitwrite();
  1523.             goto waitack;
  1524.         }
  1525.  
  1526.     } while(e == ZCRCG);
  1527.  
  1528.     waitwrite();
  1529.  
  1530.     for (;;)
  1531.     {
  1532.         if(check_abort()) return ERROR;
  1533.  
  1534.         stohdr(Txpos);
  1535.         zsbhdr(ZEOF, Txhdr);
  1536.         switch(getinsync())
  1537.         {
  1538.             case ZACK:
  1539.                 continue;
  1540.             case ZRPOS:
  1541.                 ZErrDisplay("ERROR Received");
  1542.                 goto somemore;
  1543.             case ZRINIT:
  1544.                 throughput(Txpos-STpos);
  1545.                 return OK;
  1546.             case ZSKIP:
  1547.                 return c;
  1548.             default:
  1549.                 return ERROR;
  1550.         }
  1551.     }
  1552. }
  1553.  
  1554. /*
  1555.  * Respond to receiver's complaint, get back in sync with receiver
  1556.  */
  1557. static int getinsync(void)
  1558. {
  1559.     register int c, n;
  1560.  
  1561.     for (n = 5; --n>=0;)
  1562.     {
  1563.         c = zgethdr(Rxhdr);
  1564.         purgeline();
  1565.         switch(c)
  1566.         {
  1567.             case ZCAN:
  1568.             case ZABORT:
  1569.             case ZFIN:
  1570.                 return ERROR;
  1571.             case ZRPOS:
  1572.                 /* ************************************* */
  1573.                 /*  If sending to a buffered modem, you  */
  1574.                 /*   might send a break at this point to */
  1575.                 /*   dump the modem's buffer.         */
  1576.                 Seek(fh, Rxpos, OFFSET_BEGINNING);
  1577.                 Txpos = Rxpos;
  1578.                 return c;
  1579.             case ZACK:
  1580.                 if (Txpos == Rxpos)
  1581.                     return c;
  1582.                 continue;
  1583.             case ZRINIT:
  1584.             case ZSKIP:
  1585.                 return c;
  1586.             case TIMEOUT:
  1587.                 zsrCDstat=CheckCarrier();
  1588.                 if(zsrCDstat==FALSE)        return ERROR;
  1589.                 continue;
  1590.             case ERROR :
  1591.             default:
  1592.                 zsbhdr(ZNAK, Txhdr);
  1593.                 continue;
  1594.         }
  1595.     }
  1596.     return ERROR;
  1597. }
  1598.  
  1599. /* Say "bibi" to the receiver, try to do it cleanly */
  1600. static int saybibi(void)
  1601. {
  1602.     int n;
  1603.  
  1604.     for (n = 5; --n>=0;)
  1605.     {
  1606.         stohdr(0L);        /* CAF Was zsbhdr - minor change */
  1607.         zshhdr(ZFIN, Txhdr);    /*  to make debugging easier */
  1608.         switch (zgethdr(Rxhdr))
  1609.         {
  1610.             case ZFIN:
  1611.                 sendbyte('O'); sendbyte('O');    return OK;
  1612.             case ZCAN:            return ERROR;
  1613.             case TIMEOUT:
  1614.                 continue;
  1615.         }
  1616.     }
  1617.     return ERROR;
  1618. }
  1619. int startzmodem(char *fname,int flg)
  1620. {
  1621.  int x;
  1622.  transfering = TRUE;
  1623.  if(flg){
  1624. //     return(zmodemsend(fname));      /* do zmodem send    */
  1625.        x = zmodemsend(fname);      /* do zmodem send    */
  1626.  
  1627.  } else   {
  1628. //     return(zmodemreceive(fname));   /* do zmodem receive */
  1629. //(RTS) added to stop that back flow bullshit
  1630.        x = zmodemreceive(fname);   /* do zmodem receive */
  1631. //       return(x);
  1632.  }
  1633. /*if(!CheckCarrier())
  1634. {
  1635.    DropDTR(); Delay(25L); IntDoReset(Sopt->OffHook); Delay(5L);
  1636. }*/
  1637. transfering=FALSE;
  1638. return(x);
  1639. }
  1640.